package com.tomtop.core.web.config;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tomtop.core.Context;
import com.tomtop.core.web.interceptor.CheckRepeatRequestInterceptor;
import com.tomtop.core.web.interceptor.LoggerInterceptor;

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter implements EmbeddedServletContainerCustomizer{
	@Autowired LoggerInterceptor loggerInterceptor;
	@Autowired CheckRepeatRequestInterceptor checkRepeatRequestInterceptor;
	/** 
     * 请求日志拦截
     */  
	@Override
    public void addInterceptors(InterceptorRegistry registry) {  
        registry.addInterceptor(loggerInterceptor).addPathPatterns("/**");
        registry.addInterceptor(checkRepeatRequestInterceptor).addPathPatterns("/**"); 
        super.addInterceptors(registry);
    }
	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		super.addViewControllers(registry);
	}
	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
		super.configureDefaultServletHandling(configurer);
	}
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		super.addResourceHandlers(registry);
	}
	@Override
	public void customize(ConfigurableEmbeddedServletContainer container) {
		container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,"/exception/notfound"));
		container.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/exception/notfound"));
		container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR,"/exception/server-error"));
		container.addErrorPages(new ErrorPage(HttpStatus.METHOD_NOT_ALLOWED,"/exception/server-error"));
		container.addErrorPages(new ErrorPage(HttpStatus.BAD_GATEWAY,"/exception/server-error"));
	}
	
	
	@Bean @ConfigurationProperties("server.context-parameters") Map<String, String> initParameters(){ return new HashMap<>(); }
	
	@Bean ServletRegistrationBean servletRegistration(Map<String, String> initParameters){
		ServletRegistrationBean filterRegistration=new ServletRegistrationBean(new StatViewServlet());
		filterRegistration.setAsyncSupported(true);
		filterRegistration.setEnabled(true);
		filterRegistration.addUrlMappings("/druid/*");
		filterRegistration.setInitParameters(initParameters);
		return filterRegistration;
	}
	@Bean FilterRegistrationBean filterRegistration(Map<String, String> initParameters){
		FilterRegistrationBean filterRegistration=new FilterRegistrationBean(new WebStatFilter());
		filterRegistration.setAsyncSupported(true);
		filterRegistration.setEnabled(true);
		filterRegistration.addUrlPatterns("/*");
		filterRegistration.setInitParameters(initParameters);
		return filterRegistration;
	}
	@Bean MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(ObjectMapper objectMapper){
		return new MappingJackson2HttpMessageConverter(objectMapper){
			@Override
			protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
				String callback ;
				if( StringUtils.hasText(callback=Context.getCallback()) &&!(object instanceof MappingJacksonValue)){
					MappingJacksonValue mappingJacksonValue=new MappingJacksonValue(object);
					mappingJacksonValue.setJsonpFunction(callback);
					object=mappingJacksonValue;
				} 
				super.writeInternal(object, type, outputMessage);
			}
		};
	}
}
